package com.practice.util;

import cn.hutool.core.util.ObjectUtil;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;

/**
 * 高并发容器
 * ConcurrentHashMap + AtomicReference容器的封装
 * 能够保证高并发环境下的线程安全（兼容JDK21虚拟线程），同时不会失去性能
 *
 * @author: kayn
 * @create:  2024-07-01 11:04
 **/
public class ConcurrentHashMapReference<K,V> extends ConcurrentHashMap<K,AtomicReference<V>> {

    public ConcurrentHashMapReference() {
        super();
    }

    /**
     * 获取V，需要默认值构造方法，池中不存在V时会使用构造方法构造新的V
     * @param key key
     * @param supplier 返回值构造方法
     * @return value
     */
    public V get(K key, Supplier<V> supplier) {

        // 获取容器
        AtomicReference<V> atomicReference = this.computeIfAbsent(key, keyAto -> new AtomicReference<>());

        // 尝试从容器中获取V
        V value = atomicReference.get();

        // 容器中存在V，直接返回
        if (ObjectUtil.isNotNull(value)) {
            return value;
        }

        // 容器中不存在V，supplier制造V并放入容器(双重保险)
        V v = supplier.get();
        boolean setResult = atomicReference.compareAndSet(null, v);

        // 设置成功: 返回新V(即容器中的值仍然是null)
        if (setResult) {
            return v;
        }

        // 设置失败: 返回已经存在的V (即有其他线程已经设置了值)
        return atomicReference.get();
    }
}
